package org.jeecg.modules.driver;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.util.ByteUtils;

import java.util.List;

@Slf4j
public class DriverPortocal1_0_ByteDataDecoder extends ReplayingDecoder<DriverPortocal1_0_ByteDataDecoder.DataState> { //1

    public enum DataState { //2
        HEADER,
        LENGTH,
        CONTENT_APDU,
        CONTENT_MAIN,
        CRC,
        FOOTER,
        ACK
    }

    public DriverPortocal1_0_ByteDataDecoder() {
        super(DriverPortocal1_0_ByteDataDecoder.DataState.HEADER); // 3
    }

    int totalLength = 0;
    int contentLength = 0;
    String msg_content = "";
    short headerBytes = ByteUtils.getShort(new byte[]{(byte)0xAA,(byte)0x55},0);
    short footerByte = ByteUtils.getShort(new byte[]{(byte)0x55,(byte)0xAA},0);
    long uAckInt = ByteUtils.unsigned4BytesToInt(new byte[]{0x03, 0x6C, 0x00, 0x6C},0);
    String d_command = "";
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        switch (state()) {
            case HEADER:
                byte[] dataBuf = new byte[2];
                byteBuf.readBytes(dataBuf,0,2);
                short header = ByteUtils.getShort(dataBuf,0);
                if(header == headerBytes){
                    totalLength = 0;
                    contentLength = 0;
                    d_command = "";
                    msg_content = "";
                    list.clear();
                    checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.LENGTH); // 5
                }
//                list.add(dataBuf);
//                    log.info("已发送HEADER " +  ByteUtils.toHexStringDisplay(dataBuf));
                break;
            case LENGTH:
                byte bufB = byteBuf.readByte();
                totalLength = ByteUtils.unsignedByteToInt(bufB);
                if(totalLength < 5) {
                    checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.ACK); // 5
                    break;
                }
                checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.CONTENT_APDU); // 5
//                list.add(bufB);
//                    log.info("已发送LENGTH " +  ByteUtils.toHexStringDisplay(new byte[]{bufB}));
                break;
            case CONTENT_APDU:
                dataBuf = new byte[5];
                byteBuf.readBytes(dataBuf,0,5);
                contentLength = ByteUtils.unsignedByteToInt(dataBuf[4]);
                d_command = DriverCommandList.deviceReplyCommand.get(ByteUtils.unsigned4BytesToInt(dataBuf,0));
                checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.CONTENT_MAIN); // 5
//                list.add(dataBuf);
//                log.info("已发送APDU " +  ByteUtils.toHexStringDisplay(dataBuf));
                break;
            case CONTENT_MAIN:
                dataBuf = new byte[contentLength];
                byteBuf.readBytes(dataBuf,0,contentLength);
                msg_content = new String(dataBuf,DriverPortocal1_0.ENCODING);
                checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.CRC); // 5
//                list.add(dataBuf);
//                log.info("已发送CONTENT " +  ByteUtils.toHexStringDisplay(dataBuf));
            case CRC:
                byte xor = byteBuf.readByte();
                int crc = (int)xor;
                checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.FOOTER); // 5
//                list.add(xor);
//                    log.info("已发送XOR " +  ByteUtils.toHexStringDisplay(new byte[]{xor}));
            case FOOTER:
                dataBuf = new byte[2];
                byteBuf.readBytes(dataBuf,0,2);
                short footer = ByteUtils.getShort(dataBuf,0);
                if(footer == footerByte){
                    checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.HEADER); // 5
                }
//                list.add(dataBuf);
//                    log.info("已发送FOOTER " +  ByteUtils.toHexStringDisplay(dataBuf));
                //TODO:logging
                //Pass  to next handler
                list.add(d_command + "##"+msg_content);
                break;
            case ACK:
                dataBuf = new byte[totalLength];
                byteBuf.readBytes(dataBuf,0,totalLength );
                d_command = DriverCommandList.ACK;
                msg_content = new String(new byte[]{dataBuf[0]},DriverPortocal1_0.ENCODING);
                checkpoint(DriverPortocal1_0_ByteDataDecoder.DataState.FOOTER); // 5
                break;
            default:
                throw new IllegalStateException("invalid state:" + state());
        }
    }
}
